/******
    ************************************************************************
    ******
    ** @project : XDrive_Step
    ** @brief   : Stepper motor with multi-function interface and closed loop function. 
    ** @brief   : 具有多功能接口和闭环功能的步进电机
    ** @author  : unlir (知不知啊)
    ** @contacts: QQ.1354077136
    ******
    ** @address : https://github.com/unlir/XDrive
    ******
    ************************************************************************
    ******
    ** {Stepper motor with multi-function interface and closed loop function.}
    ** Copyright (c) {2020}  {unlir(知不知啊)}
    ** 
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU General Public License as published by
    ** the Free Software Foundation, either version 3 of the License, or
    ** (at your option) any later version.
    ** 
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU General Public License for more details.
    ** 
    ** You should have received a copy of the GNU General Public License
    ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
    ******
    ************************************************************************
******/

/*****
  ** @file     : mt6816.c/h
  ** @brief    : MT6816传感器硬件驱动
  ** @versions : 1.1.1
  ** @time     : 2020/08/01
  ** @reviser  : unli (HeFei China)
  ** @explain  : null
*****/

//Oneself
#include "mt6816.h"

//Config
#include "stockpile_f303cc.h"

//Control
#include "control_config.h"

//编码器矫正数据位置(Quick)(Flash)
uint16_t *Read_QuickCali_DATA = (uint16_t*)STOCKPILE_APP_CALI_ADDR;

//GPIO输出
#define MT6816_SPI_CS_H()        gpio_bit_reset(MT6816_SPI_CS_GPIO_Port, MT6816_SPI_CS_Pin)
#define MT6816_SPI_CS_L()        gpio_bit_reset(MT6816_SPI_CS_GPIO_Port, MT6816_SPI_CS_Pin)


/****************************** MT6816_SPI ******************************/
/****************************** MT6816_SPI ******************************/
/****************************** MT6816_SPI ******************************/
MT6816_SPI_Signal_Typedef    mt6816_spi;

/**
  * @brief  MT6816_SPI采集初始化
  * @param  NULL
  * @retval NULL
**/
void REIN_MT6816_SPI_Signal_Init(void)
{
    //采集数据
    mt6816_spi.sample_data = 0;
    //输出数据
    mt6816_spi.angle = 0;

    //配置外设
    REIN_GPIO_MT6816_SPI_Init();
    REIN_SPI_MT6816_SPI_Init();
}

/**
  * @brief  MT6816_SPI采集获取角度数据
  * @param  NULL
  * @retval NULL
**/
void RINE_MT6816_SPI_Get_AngleData(void)
{
    uint16_t data_t[2];
    uint16_t data_r[2];
    uint8_t h_count;

    data_t[0] = (0x80 | 0x03) << 8;
    data_t[1] = (0x80 | 0x04) << 8;

    for(uint8_t i=0; i<3; i++){
        //读取SPI数据
        MT6816_SPI_CS_L();
        // 发送数据
        spi_i2s_data_transmit(MT6816_SPI_Get_HSPI, data_t[0]);
        // 接收数据
        data_r[0] = spi_i2s_data_receive(MT6816_SPI_Get_HSPI);
        MT6816_SPI_CS_H();
        MT6816_SPI_CS_L();
        spi_i2s_data_transmit(MT6816_SPI_Get_HSPI, data_t[1]);
        data_r[1] = spi_i2s_data_receive(MT6816_SPI_Get_HSPI);
        MT6816_SPI_CS_H();
        mt6816_spi.sample_data = ((data_r[0] & 0x00FF) << 8) | (data_r[1] & 0x00FF);

        //奇偶校验
        h_count = 0;
        for(uint8_t j=0; j<16; j++){
            if(mt6816_spi.sample_data & (0x0001 << j))
                h_count++;
        }
        if(h_count & 0x01){
            mt6816_spi.pc_flag = false;
        }
        else{
            mt6816_spi.pc_flag = true;
            break;
        }
    }

    if(mt6816_spi.pc_flag){
        mt6816_spi.angle = mt6816_spi.sample_data >> 2;
        mt6816_spi.no_mag_flag = (bool)(mt6816_spi.sample_data & (0x0001 << 1));
    }
}

/****************************** MT6816 ******************************/
/****************************** MT6816 ******************************/
/****************************** MT6816 ******************************/
MT6816_Typedef    mt6816;

/**
  * @brief  MT6816初始化
  * @param  NULL
  * @retval NULL
**/
void REIN_MT6816_Init(void)
{
#ifndef MT6816_Mode
    #error "NO define MT6816_Mode"
#endif

#if (MT6816_Mode == MT6816_Mode_SPI)
    REIN_MT6816_SPI_Signal_Init();        //初始化SPI接口
#else
    #error "MT6816_Mode Invalid !!!"
#endif

    //初始化阶段获取一次角度数据(过滤错误数据)(暂未查明复位后第一次读取数据丢失的原因)
    REIN_MT6816_Get_AngleData();

    //检查校准区数据是否有效
    mt6816.rectify_valid = true;
    for(uint16_t i=0; i<(CALI_Encode_Res); i++){
        if(Read_QuickCali_DATA[i] == 0xFFFF)
            mt6816.rectify_valid = false;
    }
}

/**
  * @brief  MT6816获取角度数据
  * @param  NULL
  * @retval NULL
**/
void REIN_MT6816_Get_AngleData(void)
{
#ifndef MT6816_Mode
    #error "NO define MT6816_Mode"
#endif

#if (MT6816_Mode == MT6816_Mode_SPI)
    RINE_MT6816_SPI_Get_AngleData();
    mt6816.angle_data = mt6816_spi.angle;
    mt6816.rectify_angle = Read_QuickCali_DATA[mt6816.angle_data];
#else
    #error "MT6816_Mode Invalid !!!"
#endif
}


















